using System.Text;
using System.Text.Json;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using UwinEducation.Shared.Models;

namespace UwinEducation.API.Middleware
{
    public class RequestResponseLoggingMiddleware
    {
        private readonly RequestDelegate _next;
        private readonly ILogger<RequestResponseLoggingMiddleware> _logger;

        public RequestResponseLoggingMiddleware(RequestDelegate next, ILogger<RequestResponseLoggingMiddleware> logger)
        {
            _next = next;
            _logger = logger;
        }

        public async Task InvokeAsync(HttpContext context)
        {
            // 记录请求
            var request = await FormatRequest(context.Request);
            _logger.LogInformation($"HTTP Request:\n{request}");

            // 获取原始响应body
            var originalBodyStream = context.Response.Body;
            using var responseBody = new MemoryStream();
            context.Response.Body = responseBody;

            try
            {
                await _next(context);

                // 记录响应
                var response = await FormatResponse(context.Response);
                _logger.LogInformation($"HTTP Response:\n{response}");

                // 复制响应流到原始stream
                await responseBody.CopyToAsync(originalBodyStream);
            }
            finally
            {
                context.Response.Body = originalBodyStream;
            }
        }

        private async Task<string> FormatRequest(HttpRequest request)
        {
            var body = string.Empty;

            // 启用请求重用
            request.EnableBuffering();

            // 读取请求body
            using (var reader = new StreamReader(
                request.Body,
                encoding: Encoding.UTF8,
                detectEncodingFromByteOrderMarks: false,
                leaveOpen: true))
            {
                body = await reader.ReadToEndAsync();
                // 重置请求body位置
                request.Body.Position = 0;
            }

            return $"{request.Method} {request.Scheme}://{request.Host}{request.Path}{request.QueryString}\n" +
                   $"Headers: {JsonConvert.SerializeObject(request.Headers)}\n" +
                   $"Body: {body}";
        }

        private async Task<string> FormatResponse(HttpResponse response)
        {
            response.Body.Seek(0, SeekOrigin.Begin);
            var text = await new StreamReader(response.Body).ReadToEndAsync();
            response.Body.Seek(0, SeekOrigin.Begin);

            return $"StatusCode: {response.StatusCode}\n" +
                   $"Headers: {JsonConvert.SerializeObject(response.Headers)}\n" +
                   $"Body: {text}";
        }
    }
} 